www.gusucode.com > VC++ DVD转换AVI程序源代码 > VC++ DVD转换AVI程序源代码/gusucode/DVD2AVI/gui.cpp

    //Download by http://www.NewXing.com
/* 
 *	Copyright (C) Chia-chen Kuo - Jan 2001
 *
 *  This file is part of DVD2AVI, a free MPEG-2 decoder
 *	
 *  DVD2AVI is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2, or (at your option)
 *  any later version.
 *   
 *  DVD2AVI is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *  GNU General Public License for more details.
 *   
 *  You should have received a copy of the GNU General Public License
 *  along with GNU Make; see the file COPYING.  If not, write to
 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
 *
 */

#define GLOBAL
extern "C"
{
#include "global.h"
#include "AC3Dec\ac3.h"
}

#define TRACK_HEIGHT	30
#define INIT_WIDTH		320
#define INIT_HEIGHT		240

#define MASKCOLOR			RGB(0, 6, 0)
#define MAX_LOADSTRING		100
#define INI_VERSION			8

#define SAVE_AVI		1
#define	SAVE_D2V		2
#define SAVE_WAV		3
#define	OPEN_D2V		4
#define OPEN_VOB		5
#define OPEN_WAV		6

#define PRIORITY_HIGH		1
#define PRIORITY_NORMAL		2
#define PRIORITY_LOW		3

BOOL PopFileDlg(PTSTR, HWND, int);
ATOM MyRegisterClass(HINSTANCE);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK Statistics(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK VideoList(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK AudioList(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK Delay(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK Luminance(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK Normalization(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
static DWORD DDColorMatch(LPDIRECTDRAWSURFACE, COLORREF);
static void ShowStatistics(int);
static void DisableControl(void);
static void ClearTrack(void);
static void CheckCPU(void);
static void CheckINI(void);
static void CheckFlag(void);
static void Recovery(void);
static void OpenVideoFile(HWND);
static void OpenAudioFile(HWND);
DWORD WINAPI ProcessWAV(LPVOID);

OPENFILENAME ofn, sfn;
int INI_Version, INIT_X, INIT_Y, Priority_Flag, LumDlg_Flag, NormDlg_Flag;
FILE *INIFile, *BMPFile;
char szPath[_MAX_PATH], szTemp[_MAX_PATH], szWindowClass[MAX_LOADSTRING];
struct _finddata_t vfpfile, seqfile;

HMENU hMenu;
HINSTANCE hInst;
HANDLE hProcess, hThread;
DWORD threadId;
HWND hLumDlg, hNormDlg;

HDC hdc;
PAINTSTRUCT ps;
HBRUSH hBrush;
int LumOffset, LumGain;

char Outfilename[MAX_FILE_NUMBER][_MAX_PATH];
int SoundDelay[MAX_FILE_NUMBER];

static unsigned char BMPHeader[54] =
{
	0x42, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x28, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x0b,
	0x00, 0x00, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	MSG msg;
	HACCEL hAccel;

	// Initialize global strings
	LoadString(hInstance, IDC_GUI, szWindowClass, MAX_LOADSTRING);
	MyRegisterClass(hInstance);

	// Perform application initialization
	hInst = hInstance;

	hWnd = CreateWindow(szWindowClass, "DVD2AVI", WS_OVERLAPPEDWINDOW & ~(WS_THICKFRAME|WS_MAXIMIZEBOX),
		CW_USEDEFAULT, 0, INIT_WIDTH, INIT_HEIGHT, NULL, NULL, hInstance, NULL);

	CheckCPU();
	CheckINI();

	// GetSystemMetrics TITLE/MENU is not always accurate
	GetClientRect(hWnd, &crect);
	Edge_Width = INIT_WIDTH - crect.right;
	Edge_Height = INIT_HEIGHT - crect.bottom;

	Coded_Picture_Width = INIT_WIDTH;
	Coded_Picture_Height = INIT_HEIGHT;

	MoveWindow(hWnd, INIT_X, INIT_Y, Coded_Picture_Width+Edge_Width,
		Coded_Picture_Height+Edge_Height+TRACK_HEIGHT, true);

	hTrack = CreateWindow(TRACKBAR_CLASS, NULL,
		WS_CHILD | WS_VISIBLE | WS_DISABLED | TBS_ENABLESELRANGE | TBS_NOTICKS | TBS_TOP,
		0, Coded_Picture_Height, Coded_Picture_Width-4*TRACK_HEIGHT, TRACK_HEIGHT, hWnd, (HMENU) ID_TRACKBAR, hInst, NULL);
	SendMessage(hTrack, TBM_SETRANGE, (WPARAM) true, (LPARAM) MAKELONG(0, TRACK_PITCH));

	hLeftButton = CreateWindow("BUTTON", "[",
		WS_CHILD | WS_VISIBLE | WS_DLGFRAME | WS_DISABLED,
		Coded_Picture_Width-4*TRACK_HEIGHT, Coded_Picture_Height,
		TRACK_HEIGHT, TRACK_HEIGHT, hWnd, (HMENU) ID_LEFT_BUTTON, hInst, NULL);

	hLeftArrow = CreateWindow("BUTTON", "<",
		WS_CHILD | WS_VISIBLE | WS_DLGFRAME | WS_DISABLED,
		Coded_Picture_Width-3*TRACK_HEIGHT, Coded_Picture_Height,
		TRACK_HEIGHT, TRACK_HEIGHT, hWnd, (HMENU) ID_LEFT_ARROW, hInst, NULL);

	hRightArrow = CreateWindow("BUTTON", ">",
		WS_CHILD | WS_VISIBLE | WS_DLGFRAME | WS_DISABLED,
		Coded_Picture_Width-2*TRACK_HEIGHT, Coded_Picture_Height,
		TRACK_HEIGHT, TRACK_HEIGHT, hWnd, (HMENU) ID_RIGHT_ARROW, hInst, NULL);

	hRightButton = CreateWindow("BUTTON", "]",
		WS_CHILD | WS_VISIBLE | WS_DLGFRAME | WS_DISABLED,
		Coded_Picture_Width-TRACK_HEIGHT, Coded_Picture_Height,
		TRACK_HEIGHT, TRACK_HEIGHT, hWnd, (HMENU) ID_RIGHT_BUTTON, hInst, NULL);

	ShowWindow(hWnd, nCmdShow);

	CheckFlag();

	// Load accelerators
	hAccel = LoadAccelerators(hInstance, (LPCTSTR)IDR_ACCELERATOR);

	// Main message loop
	while (GetMessage(&msg, NULL, 0, 0)) 
	{
		if (!TranslateAccelerator(hWnd, hAccel, &msg))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}

	return msg.wParam;
}

// Processes messages for the main window
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	DWORD wmId, wmEvent;
	int i, j;

	switch (message)
	{
		case WM_CREATE:
			DragAcceptFiles(hWnd, true);

			LumGain = 128; LumGainMask = 0x0080008000800080;

			hDC = GetDC(hWnd);
			hBrush = CreateSolidBrush(MASKCOLOR);
			hMenu = GetMenu(hWnd);
			hProcess = GetCurrentProcess();

			for (i=0; i<8; i++)
			{
				p_block[i] = (short *)malloc(sizeof(short)*64 + 64);
				block[i]   = (short *)((long)p_block[i] + 64 - (long)p_block[i]%64);
			}

			p_fTempArray = (void *)malloc(sizeof(float)*128 + 64);
		    fTempArray = (void *)((long)p_fTempArray + 64 - (long)p_fTempArray%64);

			Initialize_REF_IDCT();
			Initialize_FPU_IDCT();

			// register VFAPI
			HKEY key;
			DWORD trash;

			if (RegCreateKeyEx(HKEY_CURRENT_USER, "Software\\VFPlugin", 0, "",
				REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &key, &trash) == ERROR_SUCCESS)
			{
				if (_getcwd(szBuffer, _MAX_PATH)!=NULL)
				{
					if (szBuffer[strlen(szBuffer)-1] != '\\')
						strcat(szBuffer, "\\");

					strcpy(szPath, szBuffer);

					if (_findfirst("DVD2AVI.vfp", &vfpfile) != -1L)
					{
						strcat(szBuffer, "DVD2AVI.vfp");

						RegSetValueEx(key, "DVD2AVI", 0, REG_SZ, (LPBYTE)szBuffer, strlen(szBuffer));
						CheckMenuItem(hMenu, IDM_VFAPI, MF_CHECKED);
					}

					RegCloseKey(key);
				}
			}
			break;

		case WM_COMMAND:
			wmId    = LOWORD(wParam);
			wmEvent = HIWORD(wParam);

			// parse the menu selections
			switch (wmId)
			{
				case IDM_OPEN:
					DialogBox(hInst, (LPCTSTR)IDD_FILELIST, hWnd, (DLGPROC)VideoList);
					break;

				case IDM_PREVIEW:
					Display_Flag = true;

					EnableMenuItem(hMenu, IDM_OPEN, MF_GRAYED);
					EnableMenuItem(hMenu, IDM_PREVIEW, MF_GRAYED);
					EnableMenuItem(hMenu, IDM_SAVE, MF_GRAYED);
					EnableMenuItem(hMenu, IDM_LOAD_D2V, MF_GRAYED);
					EnableMenuItem(hMenu, IDM_SAVE_D2V, MF_GRAYED);
					EnableMenuItem(hMenu, IDM_PAUSE, MF_ENABLED);
					EnableMenuItem(hMenu, IDM_STOP, MF_ENABLED);
					EnableMenuItem(GetSubMenu(hMenu, 1), 1, MF_BYPOSITION | MF_GRAYED);

					DisableControl();
					ShowStatistics(1);

					process.locate = LOCATE_RIP;

					if (WaitForSingleObject(hThread, INFINITE)==WAIT_OBJECT_0)
						hThread = CreateThread(NULL, 0, MPEG2Dec, 0, 0, &threadId);

					break;

				case IDM_SAVE:
					if (PopFileDlg(szOutput, hWnd, SAVE_AVI))
					{
						AVI_Flag = true;
						Display_Flag = false;

						EnableMenuItem(hMenu, IDM_OPEN, MF_GRAYED);
						EnableMenuItem(hMenu, IDM_PREVIEW, MF_GRAYED);
						EnableMenuItem(hMenu, IDM_SAVE, MF_GRAYED);
						EnableMenuItem(hMenu, IDM_LOAD_D2V, MF_GRAYED);
						EnableMenuItem(hMenu, IDM_SAVE_D2V, MF_GRAYED);
						EnableMenuItem(hMenu, IDM_STOP, MF_ENABLED);
						EnableMenuItem(hMenu, IDM_PAUSE, MF_ENABLED);

						EnableMenuItem(hMenu, 1, MF_BYPOSITION | MF_GRAYED);
						EnableMenuItem(hMenu, 2, MF_BYPOSITION | MF_GRAYED);

						if (LumDlg_Flag)
							EnableWindow(hLumDlg, false);
						if (NormDlg_Flag)
							EnableWindow(hNormDlg, false);

						DisableControl();
						ShowStatistics(1);

						process.locate = LOCATE_RIP;

						if (WaitForSingleObject(hThread, INFINITE)==WAIT_OBJECT_0)
							hThread = CreateThread(NULL, 0, MPEG2Dec, 0, 0, &threadId);
					}
					break;

				case IDM_PROCESS_WAV:
					DialogBox(hInst, (LPCTSTR)IDD_FILELIST, hWnd, (DLGPROC)AudioList);
					break;

				case IDM_SAVE_D2V:
					if (PopFileDlg(szOutput, hWnd, SAVE_D2V))
					{
						sprintf(szBuffer, "%s.d2v", szOutput);

						D2VFile = fopen(szBuffer, "w+");
						i = File_Limit;

						fprintf(D2VFile, "DVD2AVIProjectFile\n%d\n", i);
						while (i)
						{
							fprintf(D2VFile, "%d %s\n", strlen(Infilename[File_Limit-i]), Infilename[File_Limit-i]);
							i--;
						}

						D2V_Flag = true;
						Display_Flag = false;

						EnableMenuItem(hMenu, IDM_OPEN, MF_GRAYED);
						EnableMenuItem(hMenu, IDM_PREVIEW, MF_GRAYED);
						EnableMenuItem(hMenu, IDM_SAVE, MF_GRAYED);
						EnableMenuItem(hMenu, IDM_LOAD_D2V, MF_GRAYED);
						EnableMenuItem(hMenu, IDM_SAVE_D2V, MF_GRAYED);
						EnableMenuItem(hMenu, IDM_STOP, MF_ENABLED);
						EnableMenuItem(hMenu, IDM_PAUSE, MF_ENABLED);

						EnableMenuItem(hMenu, 1, MF_BYPOSITION | MF_GRAYED);
						EnableMenuItem(hMenu, 2, MF_BYPOSITION | MF_GRAYED);

						if (LumDlg_Flag)
							EnableWindow(hLumDlg, false);
						if (NormDlg_Flag)
							EnableWindow(hNormDlg, false);

						DisableControl();
						ShowStatistics(1);

						process.locate = LOCATE_RIP;

						if (WaitForSingleObject(hThread, INFINITE)==WAIT_OBJECT_0)
							hThread = CreateThread(NULL, 0, MPEG2Dec, 0, 0, &threadId);
					}
					break;

				case IDM_LOAD_D2V:
					if (PopFileDlg(szInput, hWnd, OPEN_D2V))
					{
D2V_PROCESS:
						D2VFile = fopen(szInput, "r");

						while (File_Limit)
						{
							File_Limit--;
							_close(Infile[File_Limit]);
						}

						fscanf(D2VFile, "DVD2AVIProjectFile\n%d\n", &File_Limit);

						i = File_Limit;
						while (i)
						{
							fscanf(D2VFile, "%d ", &j);
							fgets(Infilename[File_Limit-i], j+1, D2VFile);
							if ((Infile[File_Limit-i] = _open(Infilename[File_Limit-i], _O_RDONLY | _O_BINARY))==-1)
							{
								while (i<File_Limit)
								{
									_close(Infile[File_Limit-i-1]);
									i++;
								}

								File_Limit = 0;
								break;
							}

							i--;
						}

						fscanf(D2VFile, "\nSystem_Stream=%d\n", &SystemStream_Flag);
						fscanf(D2VFile, "iDCT_Algorithm=%d\n", &iDCT_Flag);
						fscanf(D2VFile, "YUVRGB_Scale=%d\n", &Scale_Flag);
						fscanf(D2VFile, "Lum_Gain=%d\n", &LumGain);
						fscanf(D2VFile, "Lum_Offset=%d\n", &LumOffset);
						LumGainMask = ((__int64)LumGain<<48) + ((__int64)LumGain<<32) + ((__int64)LumGain<<16) + (__int64)LumGain;
						LumOffsetMask = ((__int64)LumOffset<<48) + ((__int64)LumOffset<<32) + ((__int64)LumOffset<<16) + (__int64)LumOffset;

						if (LumGain!=128 || LumOffset!=0)
						{
							CheckMenuItem(hMenu, IDM_LUMINANCE, MF_CHECKED);
							Luminance_Flag = true;				
						}
						else
						{
							CheckMenuItem(hMenu, IDM_LUMINANCE, MF_UNCHECKED);
							Luminance_Flag = false;
						}

						if (LumDlg_Flag)
						{
							DestroyWindow(hLumDlg);
							hLumDlg = CreateDialog(hInst, (LPCTSTR)IDD_LUMINANCE, hWnd, (DLGPROC)Luminance);
						}

						fscanf(D2VFile, "Field_Operation=%d\n", &FO_Flag);
						fscanf(D2VFile, "Frame_Rate=%d\n\n", &i);

						CheckFlag();

						ResizeWindow(INIT_WIDTH, INIT_HEIGHT);
						Recovery();

						if (File_Limit)
						{
							fscanf(D2VFile, "%d %X %d %X", &process.leftfile, &i, &process.rightfile, &j);
							process.leftlba = i;
							process.rightlba = j;

							process.startfile = process.leftfile;
							process.startloc = process.leftlba * BUFFER_SIZE;
							process.endfile = process.rightfile;
							process.endloc = (process.rightlba - 1) * BUFFER_SIZE;

							process.run = 0;
							for (i=0; i<process.startfile; i++)
								process.run += process.length[i];
							process.start = process.run + process.startloc;

							process.end = 0;
							for (i=0; i<process.endfile; i++)
								process.end += process.length[i];
							process.end += process.endloc;

							process.trackleft = (int)(process.start*TRACK_PITCH/process.total);
							process.trackright = (int)(process.end*TRACK_PITCH/process.total);

							process.locate = LOCATE_INIT;

							if (!threadId || WaitForSingleObject(hThread, INFINITE)==WAIT_OBJECT_0)
								hThread = CreateThread(NULL, 0, MPEG2Dec, 0, 0, &threadId);
						}
					}
					break;

				case IDM_STOP:
					Stop_Flag = true;

					if (Pause_Flag)
					{
						Pause_Flag = false;
						CheckMenuItem(hMenu, IDM_PAUSE, MF_UNCHECKED);
						ResumeThread(hThread);
					}
					break;

//-------------------------------------------------------------------------------------------

				case IDM_STORE_RGB24:
					if (Store_Flag!=STORE_RGB24)
					{
						if (DDOverlay_Flag)
							IDirectDrawSurface_UpdateOverlay(lpOverlay, NULL, lpPrimary, NULL, DDOVER_HIDE, NULL);

						Store_Flag = STORE_RGB24;
						CheckMenuItem(hMenu, IDM_STORE_RGB24, MF_CHECKED);
						CheckMenuItem(hMenu, IDM_STORE_YUY2, MF_UNCHECKED);
						EnableMenuItem(hMenu, IDM_BMP, MF_ENABLED);

						if (WaitForSingleObject(hThread, 0)==WAIT_OBJECT_0)
						{
							Fault_Flag = false; Display_Flag = true;
							Write_Frame(backward_reference_frame, d2v_backward, 0);
						}
					}
					break;

				case IDM_STORE_YUY2:
					if (Store_Flag!=STORE_YUY2)
					{
						Store_Flag = STORE_YUY2;
						CheckMenuItem(hMenu, IDM_STORE_RGB24, MF_UNCHECKED);
						CheckMenuItem(hMenu, IDM_STORE_YUY2, MF_CHECKED);
						EnableMenuItem(hMenu, IDM_BMP, MF_GRAYED);

						if (DDOverlay_Flag)
						{
							GetClientRect(hWnd, &crect);
							crect.bottom -= TRACK_HEIGHT;
							FillRect(hDC, &crect, hBrush);
							crect.bottom += TRACK_HEIGHT;
						}

						if (WaitForSingleObject(hThread, 0)==WAIT_OBJECT_0)
						{
							Fault_Flag = false; Display_Flag = true;
							Write_Frame(backward_reference_frame, d2v_backward, 0);
						}
					}
					break;

//--------------------------------------------------------------------------------------------

				case IDM_TRACK_NONE:
					ClearTrack();
					Track_Flag = TRACK_NONE;
					CheckMenuItem(hMenu, IDM_TRACK_NONE, MF_CHECKED);
					break;

				case IDM_TRACK_1:
					ClearTrack();
					Track_Flag = TRACK_1;
					CheckMenuItem(hMenu, IDM_TRACK_1, MF_CHECKED);
					break;

				case IDM_TRACK_2:
					ClearTrack();
					Track_Flag = TRACK_2;
					CheckMenuItem(hMenu, IDM_TRACK_2, MF_CHECKED);
					break;

				case IDM_TRACK_3:
					ClearTrack();
					Track_Flag = TRACK_3;
					CheckMenuItem(hMenu, IDM_TRACK_3, MF_CHECKED);
					break;

				case IDM_TRACK_4:
					ClearTrack();
					Track_Flag = TRACK_4;
					CheckMenuItem(hMenu, IDM_TRACK_4, MF_CHECKED);
					break;

				case IDM_TRACK_5:
					ClearTrack();
					Track_Flag = TRACK_5;
					CheckMenuItem(hMenu, IDM_TRACK_5, MF_CHECKED);
					break;

				case IDM_TRACK_6:
					ClearTrack();
					Track_Flag = TRACK_6;
					CheckMenuItem(hMenu, IDM_TRACK_6, MF_CHECKED);
					break;

				case IDM_TRACK_7:
					ClearTrack();
					Track_Flag = TRACK_7;
					CheckMenuItem(hMenu, IDM_TRACK_7, MF_CHECKED);
					break;

				case IDM_TRACK_8:
					ClearTrack();
					Track_Flag = TRACK_8;
					CheckMenuItem(hMenu, IDM_TRACK_8, MF_CHECKED);
					break;

				case IDM_AC3:
					Format_Flag = FORMAT_AC3;
					CheckMenuItem(hMenu, IDM_AC3, MF_CHECKED);
					CheckMenuItem(hMenu, IDM_MPA, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_LPCM, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_SELECT, MF_UNCHECKED);
					break;

				case IDM_MPA:
					Format_Flag = FORMAT_MPA;
					CheckMenuItem(hMenu, IDM_AC3, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_MPA, MF_CHECKED);
					CheckMenuItem(hMenu, IDM_LPCM, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_SELECT, MF_UNCHECKED);
					break;

				case IDM_LPCM:
					Format_Flag = FORMAT_LPCM;
					CheckMenuItem(hMenu, IDM_AC3, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_MPA, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_LPCM, MF_CHECKED);
					CheckMenuItem(hMenu, IDM_SELECT, MF_UNCHECKED);
					break;

				case IDM_AC3_DEMUXALL:
					AC3_Flag = AUDIO_DEMUXALL;
					CheckMenuItem(hMenu, IDM_AC3_DEMUXALL, MF_CHECKED);
					CheckMenuItem(hMenu, IDM_AC3_DEMUXONE, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_AC3_DECODE, MF_UNCHECKED);
					break;

				case IDM_AC3_DEMUXONE:
					AC3_Flag = AUDIO_DEMUXONE;
					CheckMenuItem(hMenu, IDM_AC3_DEMUXALL, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_AC3_DEMUXONE, MF_CHECKED);
					CheckMenuItem(hMenu, IDM_AC3_DECODE, MF_UNCHECKED);
					break;

				case IDM_AC3_DECODE:
					AC3_Flag = AUDIO_DECODE;
					CheckMenuItem(hMenu, IDM_AC3_DEMUXALL, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_AC3_DEMUXONE, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_AC3_DECODE, MF_CHECKED);
					break;

				case IDM_DRC_NONE:
					DRC_Flag = DRC_NONE;
					CheckMenuItem(hMenu, IDM_DRC_NONE, MF_CHECKED);
					CheckMenuItem(hMenu, IDM_DRC_LIGHT, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_DRC_NORMAL, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_DRC_HEAVY, MF_UNCHECKED);
					break;

				case IDM_DRC_LIGHT:
					DRC_Flag = DRC_LIGHT;
					CheckMenuItem(hMenu, IDM_DRC_NONE, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_DRC_LIGHT, MF_CHECKED);
					CheckMenuItem(hMenu, IDM_DRC_NORMAL, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_DRC_HEAVY, MF_UNCHECKED);
					break;

				case IDM_DRC_NORMAL:
					DRC_Flag = DRC_NORMAL;
					CheckMenuItem(hMenu, IDM_DRC_NONE, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_DRC_LIGHT, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_DRC_NORMAL, MF_CHECKED);
					CheckMenuItem(hMenu, IDM_DRC_HEAVY, MF_UNCHECKED);
					break;

				case IDM_DRC_HEAVY:
					DRC_Flag = DRC_HEAVY;
					CheckMenuItem(hMenu, IDM_DRC_NONE, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_DRC_LIGHT, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_DRC_NORMAL, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_DRC_HEAVY, MF_CHECKED);
					break;

				case IDM_DSDOWN:
					if (DSDown_Flag)
						CheckMenuItem(hMenu, IDM_DSDOWN, MF_UNCHECKED);
					else
						CheckMenuItem(hMenu, IDM_DSDOWN, MF_CHECKED);

					DSDown_Flag = !DSDown_Flag;
					break;

				case IDM_MPA_DEMUXALL:
					MPA_Flag = AUDIO_DEMUXALL;
					CheckMenuItem(hMenu, IDM_MPA_DEMUXALL, MF_CHECKED);
					CheckMenuItem(hMenu, IDM_MPA_DEMUXONE, MF_UNCHECKED);
					break;

				case IDM_MPA_DEMUXONE:
					MPA_Flag = AUDIO_DEMUXONE;
					CheckMenuItem(hMenu, IDM_MPA_DEMUXALL, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_MPA_DEMUXONE, MF_CHECKED);
					break;

				case IDM_SELECT:
					Format_Flag = FORMAT_AUTO;
					CheckMenuItem(hMenu, IDM_AC3, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_MPA, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_LPCM, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_SELECT, MF_CHECKED);
					break;

//-------------------------------------------------------------------------------------------

				case IDM_IDCT_MMX:
					iDCT_Flag = IDCT_MMX;
					CheckMenuItem(hMenu, IDM_IDCT_REF, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_IDCT_MMX, MF_CHECKED);
					CheckMenuItem(hMenu, IDM_IDCT_FPU, MF_UNCHECKED);
					break;

				case IDM_IDCT_FPU:
					iDCT_Flag = IDCT_FPU;
					CheckMenuItem(hMenu, IDM_IDCT_REF, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_IDCT_MMX, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_IDCT_FPU, MF_CHECKED);
					break;

				case IDM_IDCT_REF:
					iDCT_Flag = IDCT_REF;
					CheckMenuItem(hMenu, IDM_IDCT_REF, MF_CHECKED);
					CheckMenuItem(hMenu, IDM_IDCT_MMX, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_IDCT_FPU, MF_UNCHECKED);
					break;

				case IDM_FO_NONE:
					FO_Flag = FO_NONE;
					CheckMenuItem(hMenu, IDM_FO_NONE, MF_CHECKED);
					CheckMenuItem(hMenu, IDM_FO_FILM, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_FO_SWAP, MF_UNCHECKED);
					SetDlgItemText(hDlg, IDC_DEBUG, "");
					break;

				case IDM_FO_FILM:
					FO_Flag = FO_FILM;
					CheckMenuItem(hMenu, IDM_FO_NONE, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_FO_FILM, MF_CHECKED);
					CheckMenuItem(hMenu, IDM_FO_SWAP, MF_UNCHECKED);
					SetDlgItemText(hDlg, IDC_DEBUG, "");
					break;

				case IDM_FO_SWAP:
					FO_Flag = FO_SWAP;
					CheckMenuItem(hMenu, IDM_FO_NONE, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_FO_FILM, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_FO_SWAP, MF_CHECKED);
					SetDlgItemText(hDlg, IDC_DEBUG, "");
					break;

				case IDM_TVSCALE:
					Scale_Flag = false;
					YUVRGB_Scale = 0x1000200010002000;
					YUVRGB_Offset = 0x0000000000000000;
					CheckMenuItem(hMenu, IDM_TVSCALE, MF_CHECKED);
					CheckMenuItem(hMenu, IDM_PCSCALE, MF_UNCHECKED);

					if (WaitForSingleObject(hThread, 0)==WAIT_OBJECT_0)
					{
						Fault_Flag = false; Display_Flag = true;
						Write_Frame(backward_reference_frame, d2v_backward, 0);
					}
					break;

				case IDM_PCSCALE:
					Scale_Flag = true;
					YUVRGB_Scale = 0x1000254310002543;
					YUVRGB_Offset = 0x0010001000100010;
					CheckMenuItem(hMenu, IDM_TVSCALE, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_PCSCALE, MF_CHECKED);

					if (WaitForSingleObject(hThread, 0)==WAIT_OBJECT_0)
					{
						Fault_Flag = false; Display_Flag = true;
						Write_Frame(backward_reference_frame, d2v_backward, 0);
					}
					break;

				case IDM_LUMINANCE:
					if (LumDlg_Flag)
					{
						DestroyWindow(hLumDlg);
						LumDlg_Flag = false;
					}
					else
						hLumDlg = CreateDialog(hInst, (LPCTSTR)IDD_LUMINANCE, hWnd, (DLGPROC)Luminance);
					break;

				case IDM_NORM:
					if (NormDlg_Flag)
					{
						DestroyWindow(hNormDlg);
						NormDlg_Flag = false;
					}
					else
						hNormDlg = CreateDialog(hInst, (LPCTSTR)IDD_NORM, hWnd, (DLGPROC)Normalization);
					break;

//---------------------------------------------------------------------------------------

				case IDM_PP_HIGH:
					Priority_Flag = PRIORITY_HIGH;
					SetPriorityClass(hProcess, HIGH_PRIORITY_CLASS);
					CheckMenuItem(hMenu, IDM_PP_HIGH, MF_CHECKED);
					CheckMenuItem(hMenu, IDM_PP_NORMAL, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_PP_LOW, MF_UNCHECKED);
					break;

				case IDM_PP_NORMAL:
					Priority_Flag = PRIORITY_NORMAL;
					SetPriorityClass(hProcess, NORMAL_PRIORITY_CLASS);
					CheckMenuItem(hMenu, IDM_PP_HIGH, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_PP_NORMAL, MF_CHECKED);
					CheckMenuItem(hMenu, IDM_PP_LOW, MF_UNCHECKED);
					break;

				case IDM_PP_LOW:
					Priority_Flag = PRIORITY_LOW;
					SetPriorityClass(hProcess, IDLE_PRIORITY_CLASS);
					CheckMenuItem(hMenu, IDM_PP_HIGH, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_PP_NORMAL, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_PP_LOW, MF_CHECKED);
					break;

				case IDM_PAUSE:
					if (Pause_Flag)
					{
						ResumeThread(hThread);
						CheckMenuItem(hMenu, IDM_PAUSE, MF_UNCHECKED);
					}
					else
					{
						SuspendThread(hThread);
						CheckMenuItem(hMenu, IDM_PAUSE, MF_CHECKED);
					}

					Pause_Flag = !Pause_Flag;
					break;

				case IDM_STATISTICS:
					if (Statistics_Flag)
					{
						DestroyWindow(hDlg);
						Statistics_Flag = false;
						hDlg = NULL;
					}
					else
						ShowStatistics(1);
					break;

				case IDM_DISPLAY:
					Display_Flag = !Display_Flag;
					break;

				case IDM_BMP:
					SYSTEMTIME st;
					GetLocalTime(&st);

					sprintf(szTemp, "%sDVD2AVI %02d%02d%02d%02d%02d.bmp", szPath, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
					BMPFile = fopen(szTemp, "wb");

					i = fwrite(BMPHeader, 1, sizeof(BMPHeader), BMPFile);
					i += fwrite(rgb24, 1, Coded_Picture_Width * Coded_Picture_Height * 3, BMPFile);

					j = i & 3;

					while (j>0)
					{
						i += fwrite(szBlank, 1, 1, BMPFile);
						j--;
					}

					fseek(BMPFile, 2, SEEK_SET);
					fwrite(&i, sizeof(int), 1, BMPFile);
					fseek(BMPFile, 18, SEEK_SET);
					fwrite(&Coded_Picture_Width, sizeof(int), 1, BMPFile);
					fwrite(&Coded_Picture_Height, sizeof(int), 1, BMPFile);
					
					fclose(BMPFile);
					break;

//----------------------------------------------------------------------------------------

				case IDM_SRC_NONE:
					SRC_Flag = SRC_NONE;
					CheckMenuItem(hMenu, IDM_SRC_NONE, MF_CHECKED);
					CheckMenuItem(hMenu, IDM_SRC_LOW, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_SRC_MID, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_SRC_HIGH, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_SRC_UHIGH, MF_UNCHECKED);
					break;

				case IDM_SRC_LOW:
					SRC_Flag = SRC_LOW;
					CheckMenuItem(hMenu, IDM_SRC_NONE, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_SRC_LOW, MF_CHECKED);
					CheckMenuItem(hMenu, IDM_SRC_MID, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_SRC_HIGH, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_SRC_UHIGH, MF_UNCHECKED);
					break;

				case IDM_SRC_MID:
					SRC_Flag = SRC_MID;
					CheckMenuItem(hMenu, IDM_SRC_NONE, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_SRC_LOW, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_SRC_MID, MF_CHECKED);
					CheckMenuItem(hMenu, IDM_SRC_HIGH, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_SRC_UHIGH, MF_UNCHECKED);
					break;

				case IDM_SRC_HIGH:
					SRC_Flag = SRC_HIGH;
					CheckMenuItem(hMenu, IDM_SRC_NONE, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_SRC_LOW, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_SRC_MID, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_SRC_HIGH, MF_CHECKED);
					CheckMenuItem(hMenu, IDM_SRC_UHIGH, MF_UNCHECKED);
					break;

				case IDM_SRC_UHIGH:
					SRC_Flag = SRC_UHIGH;
					CheckMenuItem(hMenu, IDM_SRC_NONE, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_SRC_LOW, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_SRC_MID, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_SRC_HIGH, MF_UNCHECKED);
					CheckMenuItem(hMenu, IDM_SRC_UHIGH, MF_CHECKED);
					break;

//---------------------------------------------------------------------------------------

				case IDM_ABOUT:
					DialogBox(hInst, (LPCTSTR)IDD_ABOUT, hWnd, (DLGPROC)About);
					break;

				case IDM_HOMEPAGE:
					ShellExecute(NULL, "open", "http://hiroko.ee.ntu.edu.tw/", NULL, NULL, SW_SHOWNORMAL);
					break;

				case IDM_EXIT:
					DestroyWindow(hWnd);
					break;

//----------------------------------------------------------------------------------------

				case ID_LEFT_BUTTON:
					if (IsWindowEnabled(hTrack))
					{
						SetFocus(hWnd);

						if ((process.file < process.rightfile) || (process.file==process.rightfile && process.lba<process.rightlba))
						{
							process.leftfile = process.file;
							process.leftlba = process.lba;

							process.run = 0;
							for (i=0; i<process.leftfile; i++)
								process.run += process.length[i];
							process.trackleft = (int)((process.run + process.leftlba * BUFFER_SIZE) * TRACK_PITCH / process.total);

							SendMessage(hTrack, TBM_SETPOS, (WPARAM) true, process.trackleft);
							SendMessage(hTrack, TBM_SETSEL, (WPARAM) true, (LPARAM) MAKELONG(process.trackleft, process.trackright));
						}
					}
					break;

				case ID_LEFT_ARROW:
					if (IsWindowEnabled(hTrack))
					{
						SetFocus(hWnd);

						if (WaitForSingleObject(hThread, 0)==WAIT_OBJECT_0)
						{
							Display_Flag = true;

							process.locate = LOCATE_BACKWARD;
							hThread = CreateThread(NULL, 0, MPEG2Dec, 0, 0, &threadId);
						}
					}
					break;

				case ID_RIGHT_ARROW:
					if (IsWindowEnabled(hTrack))
					{
						SetFocus(hWnd);

						if (WaitForSingleObject(hThread, 0)==WAIT_OBJECT_0)
						{
							Display_Flag = true;

							process.locate = LOCATE_FORWARD;
							hThread = CreateThread(NULL, 0, MPEG2Dec, 0, 0, &threadId);
						}
					}
					break;

				case ID_RIGHT_BUTTON:
					if (IsWindowEnabled(hTrack))
					{
						SetFocus(hWnd);

						if ((process.file>process.leftfile) || (process.file==process.leftfile && process.lba>process.leftlba))
						{
							process.rightfile = process.file;
							process.rightlba = process.lba;

							process.run = 0;
							for (i=0; i<process.rightfile; i++)
								process.run += process.length[i];
							process.trackright = (int)((process.run + (__int64)process.rightlba*BUFFER_SIZE)*TRACK_PITCH/process.total);

							SendMessage(hTrack, TBM_SETPOS, (WPARAM) true, process.trackright);
							SendMessage(hTrack, TBM_SETSEL, (WPARAM) true, (LPARAM) MAKELONG(process.trackleft, process.trackright));
						}
					}
					break;

				default:
					return DefWindowProc(hWnd, message, wParam, lParam);
			}
			break;

		case WM_HSCROLL:
			SetFocus(hWnd);

			if (WaitForSingleObject(hThread, 0)==WAIT_OBJECT_0)
			{
				Display_Flag = true;

				process.startloc = process.start = process.total*SendMessage(hTrack, TBM_GETPOS, 0, 0)/TRACK_PITCH;

				process.startfile = 0; process.run = 0;
				while (process.startloc > process.length[process.startfile])
				{
					process.startloc -= process.length[process.startfile];
					process.run += process.length[process.startfile];
					process.startfile++;
				}

				process.end = process.total - BUFFER_SIZE;
				process.endfile = File_Limit - 1;
				process.endloc = (process.length[File_Limit-1]/BUFFER_SIZE-1)*BUFFER_SIZE;

				process.locate = LOCATE_SCROLL;

				hThread = CreateThread(NULL, 0, MPEG2Dec, 0, 0, &threadId);
			}
			break;

		case WM_KEYDOWN:
			if (IsWindowEnabled(hTrack))
			{
				switch (wParam)
				{
					case VK_LEFT:
						if (WaitForSingleObject(hThread, 0)==WAIT_OBJECT_0)
						{
							Display_Flag = true;

							process.locate = LOCATE_BACKWARD;
							hThread = CreateThread(NULL, 0, MPEG2Dec, 0, 0, &threadId);
						}
						break;

					case VK_RIGHT:
						if (WaitForSingleObject(hThread, 0)==WAIT_OBJECT_0)
						{
							Display_Flag = true;

							process.locate = LOCATE_FORWARD;
							hThread = CreateThread(NULL, 0, MPEG2Dec, 0, 0, &threadId);
						}
						break;
				}
			}
			break;

		case WM_SIZE:
			if (!IsIconic(hWnd))
				ShowStatistics(0);

			if (DDOverlay_Flag)
				IDirectDrawSurface_UpdateOverlay(lpOverlay, NULL, lpPrimary, NULL, DDOVER_HIDE, NULL);

			break;

		case WM_MOVE:
			if (!IsIconic(hWnd))
				ShowStatistics(0);

			if (Check_Flag)
			{
				if (DDOverlay_Flag && Store_Flag==STORE_YUY2)
					RenderYUY2();
				else
					RenderRGB24();
			}
			break;

		case WM_PAINT:
			if (Check_Flag && Store_Flag==STORE_RGB24)
				RenderRGB24();

			hdc = BeginPaint(hWnd, &ps);
			EndPaint(hWnd, &ps);
			ReleaseDC(hWnd, hdc);
			break;

		case WM_DROPFILES:
			char seq, *ext;

			DragQueryFile((HDROP)wParam, 0, szInput, sizeof(szInput));
			DragFinish((HDROP)wParam);

			ext = strrchr(szInput, '.');
			if (ext!=NULL)
			{
				if (!_strnicmp(ext, ".d2v", 4))
					goto D2V_PROCESS;

				if (!_strnicmp(ext, ".wav", 4))
				{
					if (Check_Flag)
						break;

					if (!CheckWAV())
					{
						DialogBox(hInst, (LPCTSTR)IDD_ERROR, hWnd, (DLGPROC)About);
						break;
					}

					if (PopFileDlg(szOutput, hWnd, SAVE_WAV))
					{
						DialogBox(hInst, (LPCTSTR)IDD_DELAY, hWnd, (DLGPROC)Delay);
						ShowStatistics(1);

						if (!threadId || WaitForSingleObject(hThread, INFINITE)==WAIT_OBJECT_0)
							hThread = CreateThread(NULL, 0, ProcessWAV, 0, 0, &threadId);
					}
					break;
				}
			}

			while (File_Limit)
			{
				File_Limit--;
				_close(Infile[File_Limit]);
			}

			while (_findfirst(szInput, &seqfile) != -1L)
			{
				strcpy(Infilename[File_Limit], szInput);
				Infile[File_Limit] = _open(szInput, _O_RDONLY | _O_BINARY);
				File_Limit++;

				strncpy(&seq, szInput+strlen(szInput)-5, 1);
				if (seq<'9')
					seq++;
				else
					break;
				strncpy(szInput+strlen(szInput)-5, &seq, 1);
			}

			ResizeWindow(INIT_WIDTH, INIT_HEIGHT);
			Recovery();

			if (File_Limit)
			{
				process.rightfile = File_Limit-1;
				process.rightlba = (int)(process.length[File_Limit-1]/BUFFER_SIZE);

				process.end = process.total - BUFFER_SIZE;
				process.endfile = File_Limit - 1;
				process.endloc = (process.length[File_Limit-1]/BUFFER_SIZE - 1)*BUFFER_SIZE;

				process.locate = LOCATE_INIT;

				if (!threadId || WaitForSingleObject(hThread, INFINITE)==WAIT_OBJECT_0)
					hThread = CreateThread(NULL, 0, MPEG2Dec, 0, 0, &threadId);
			}
			break;

		case WM_DESTROY:
			strcat(szPath, "DVD2AVI.ini");
			GetWindowRect(hWnd, &wrect);

			if ((INIFile = fopen(szPath, "w")) != NULL)
			{
				fprintf(INIFile, "INI_Version=%d\n", INI_Version);
				fprintf(INIFile, "INIT_X=%d\n", wrect.left);
				fprintf(INIFile, "INIT_Y=%d\n", wrect.top);
				fprintf(INIFile, "iDCT_Algorithm=%d\n", iDCT_Flag);
				fprintf(INIFile, "YUVRGB_Scale=%d\n", Scale_Flag);
				fprintf(INIFile, "Field_Operation=%d\n", FO_Flag);
				fprintf(INIFile, "Track_Number=%d\n", Track_Flag);
				fprintf(INIFile, "Channel_Format=%d\n", Format_Flag);
				fprintf(INIFile, "AC3=%d\n", AC3_Flag);
				fprintf(INIFile, "DR_Control=%d\n", DRC_Flag);
				fprintf(INIFile, "DS_Downmix=%d\n", DSDown_Flag);
				fprintf(INIFile, "MPA=%d\n", MPA_Flag);
				fprintf(INIFile, "SRC_Precision=%d\n", SRC_Flag);
				fprintf(INIFile, "Norm_Ratio=%d\n", 100 * Normalization_Flag + Norm_Ratio);
				fprintf(INIFile, "Process_Priority=%d\n", Priority_Flag);

				fclose(INIFile);
			}

			Recovery();

			for (i=0; i<8; i++)
				free(p_block[i]);
			free(p_fTempArray);

			ReleaseDC(hWnd, hDC);
			DeleteObject(hBrush);

			PostQuitMessage(0);
			break;

		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return false;
}

LRESULT CALLBACK VideoList(HWND hVideoListDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	int i, j;

	switch (message)
	{
		case WM_INITDIALOG:
			if (File_Limit)
				for (i=0; i<File_Limit; i++)
					SendDlgItemMessage(hVideoListDlg, IDC_LIST, LB_ADDSTRING, 0, (LPARAM)Infilename[i]);
			else
				OpenVideoFile(hVideoListDlg);

			if (File_Limit)
				SendDlgItemMessage(hVideoListDlg, IDC_LIST, LB_SETCURSEL, File_Limit-1, 0);
			return true;

		case WM_COMMAND:
			switch (LOWORD(wParam))
			{
				case ID_ADD:
					OpenVideoFile(hVideoListDlg);

					if (File_Limit)
						SendDlgItemMessage(hVideoListDlg, IDC_LIST, LB_SETCURSEL, File_Limit-1, 0);
					break;

				case ID_DEL:
					if (File_Limit)
					{
						i= SendDlgItemMessage(hVideoListDlg, IDC_LIST, LB_GETCURSEL, 0, 0);
						SendDlgItemMessage(hVideoListDlg, IDC_LIST, LB_DELETESTRING, i, 0);

						_close(Infile[i]);

						File_Limit--;

						for (j=i; j<File_Limit; j++)
						{
							Infile[j] = Infile[j+1];
							strcpy(Infilename[j], Infilename[j+1]);
						}

						SendDlgItemMessage(hVideoListDlg, IDC_LIST, LB_SETCURSEL, i>=File_Limit ? File_Limit-1 : i, 0);
					}
					break;

				case IDOK:
				case IDCANCEL:
					EndDialog(hVideoListDlg, 0);

					ResizeWindow(INIT_WIDTH, INIT_HEIGHT);
					Recovery();

					if (File_Limit)
					{
						process.rightfile = File_Limit-1;
						process.rightlba = (int)(process.length[File_Limit-1]/BUFFER_SIZE);

						process.end = process.total - BUFFER_SIZE;
						process.endfile = File_Limit - 1;
						process.endloc = (process.length[File_Limit-1]/BUFFER_SIZE - 1)*BUFFER_SIZE;

						process.locate = LOCATE_INIT;

						if (!threadId || WaitForSingleObject(hThread, INFINITE)==WAIT_OBJECT_0)
							hThread = CreateThread(NULL, 0, MPEG2Dec, 0, 0, &threadId);
					}
					return true;
			}
			break;
	}
    return false;
}

static void OpenVideoFile(HWND hVideoListDlg)
{
	char seq;

	if (PopFileDlg(szInput, hVideoListDlg, OPEN_VOB))
	{
		while (_findfirst(szInput, &seqfile) != -1L)
		{
			SendDlgItemMessage(hVideoListDlg, IDC_LIST, LB_ADDSTRING, 0, (LPARAM)szInput);
			strcpy(Infilename[File_Limit], szInput);
			Infile[File_Limit] = _open(szInput, _O_RDONLY | _O_BINARY);
			File_Limit++;

			strncpy(&seq, szInput+strlen(szInput)-5, 1);
			if (seq<'9')
				seq++;
			else
				break;
			strncpy(szInput+strlen(szInput)-5, &seq, 1);
		}
	}
}

LRESULT CALLBACK AudioList(HWND hAudioListDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	int i, j;

	switch (message)
	{
		case WM_INITDIALOG:
			File_Limit = 0;
			OpenAudioFile(hAudioListDlg);
			return true;

		case WM_COMMAND:
			switch (LOWORD(wParam))
			{
				case ID_ADD:
					OpenAudioFile(hAudioListDlg);
					break;

				case ID_DEL:
					if (File_Limit)
					{
						i= SendDlgItemMessage(hAudioListDlg, IDC_LIST, LB_GETCURSEL, 0, 0);
						SendDlgItemMessage(hAudioListDlg, IDC_LIST, LB_DELETESTRING, i, 0);

						File_Limit--;

						for (j=i; j<File_Limit; j++)
						{
							strcpy(Infilename[j], Infilename[j+1]);
							strcpy(Outfilename[j], Outfilename[j+1]);
							SoundDelay[j] = SoundDelay[j+1];
						}

						SendDlgItemMessage(hAudioListDlg, IDC_LIST, LB_SETCURSEL, i>=File_Limit ? File_Limit-1 : i, 0);
					}
					break;

				case IDOK:
				case IDCANCEL:
					EndDialog(hAudioListDlg, 0);

					if (File_Limit)
					{
						ShowStatistics(1);

						if (!threadId || WaitForSingleObject(hThread, INFINITE)==WAIT_OBJECT_0)
							hThread = CreateThread(NULL, 0, ProcessWAV, (void *)File_Limit, 0, &threadId);
					}
					return true;
			}
			break;
	}
    return false;
}

static void OpenAudioFile(HWND hAudioListDlg)
{
	if (PopFileDlg(szInput, hAudioListDlg, OPEN_WAV))
	{
		if (!CheckWAV())
		{
			DialogBox(hInst, (LPCTSTR)IDD_ERROR, hAudioListDlg, (DLGPROC)About);
			return;
		}

		if (PopFileDlg(szOutput, hAudioListDlg, SAVE_WAV))
		{
			strcpy(Infilename[File_Limit], szInput);
			strcpy(Outfilename[File_Limit], szOutput);
			DialogBox(hInst, (LPCTSTR)IDD_DELAY, hWnd, (DLGPROC)Delay);
			sprintf(szBuffer, "%s %dms", szInput, SoundDelay[File_Limit]);
			SendDlgItemMessage(hAudioListDlg, IDC_LIST, LB_ADDSTRING, 0, (LPARAM)szBuffer);
			File_Limit++;
		}
	}

	if (File_Limit)
		SendDlgItemMessage(hAudioListDlg, IDC_LIST, LB_SETCURSEL, File_Limit-1, 0);
}

DWORD WINAPI ProcessWAV(LPVOID n)
{
	int i;
	Stop_Flag = false;

	EnableMenuItem(hMenu, IDM_OPEN, MF_GRAYED);
	EnableMenuItem(hMenu, IDM_PROCESS_WAV, MF_GRAYED);
	EnableMenuItem(hMenu, IDM_LOAD_D2V, MF_GRAYED);
	EnableMenuItem(hMenu, IDM_STOP, MF_ENABLED);
	EnableMenuItem(hMenu, 2, MF_BYPOSITION | MF_GRAYED);

	DragAcceptFiles(hWnd, false);

	if (!n)
		Wavefs44File(SoundDelay[0], 1, 1);
	else
		for (i=0; i<File_Limit && !Stop_Flag; i++)
		{
			strcpy(szInput, Infilename[i]);
			strcpy(szOutput, Outfilename[i]);
			Wavefs44File(SoundDelay[i], i+1, File_Limit);
		}

	File_Limit = 0;

	EnableMenuItem(hMenu, IDM_OPEN, MF_ENABLED);
	EnableMenuItem(hMenu, IDM_PROCESS_WAV, MF_ENABLED);
	EnableMenuItem(hMenu, IDM_LOAD_D2V, MF_ENABLED);
	EnableMenuItem(hMenu, IDM_STOP, MF_GRAYED);
	EnableMenuItem(hMenu, 2, MF_BYPOSITION | MF_ENABLED);

	if (!Stop_Flag)
	{
		SetDlgItemText(hDlg, IDC_REMAIN, "FINISH");
		MessageBeep(MB_OK);
	}

	DragAcceptFiles(hWnd, true);
	return 0;
}

void ThreadKill()
{
	if (Check_Flag)
	{
		if ((AVI_Flag || D2V_Flag) && Track_Flag!=TRACK_NONE && 
			((ac3[Track_Flag].rip && AC3_Flag==AUDIO_DECODE) || pcm.rip))
		{
			if (SRC_Flag)
			{
				EndSRC(pcm.file);
				pcm.size = ((int)(0.91875*pcm.size)>>2)<<2;
			}
				
			Normalize(NULL, 44, pcm.filename, pcm.file, 44, pcm.size);
			EndWAV(pcm.file, pcm.size);
		}

		if (process.locate==LOCATE_INIT || process.locate==LOCATE_RIP)
		{
			if (D2V_Flag)
				fprintf(D2VFile, " 9");

			_fcloseall();

			AVI_Flag = false;
			D2V_Flag = false;
			Display_Flag = false;

			EnableMenuItem(hMenu, IDM_OPEN, MF_ENABLED);
			EnableMenuItem(hMenu, IDM_PREVIEW, MF_ENABLED);
			EnableMenuItem(hMenu, IDM_SAVE, MF_ENABLED);
			EnableMenuItem(hMenu, IDM_LOAD_D2V, MF_ENABLED);
			EnableMenuItem(hMenu, IDM_SAVE_D2V, MF_ENABLED);
			EnableMenuItem(hMenu, IDM_STOP, MF_GRAYED);
			EnableMenuItem(hMenu, IDM_PAUSE, MF_GRAYED);

			EnableMenuItem(hMenu, 1, MF_BYPOSITION | MF_ENABLED);
			EnableMenuItem(hMenu, 2, MF_BYPOSITION | MF_ENABLED);
			EnableMenuItem(GetSubMenu(hMenu, 1), 1, MF_BYPOSITION | MF_ENABLED);

			if (LumDlg_Flag)
				EnableWindow(hLumDlg, true);
			if (NormDlg_Flag)
				EnableWindow(hNormDlg, true);

			EnableWindow(hTrack, true);
			EnableWindow(hLeftButton, true);
			EnableWindow(hLeftArrow, true);
			EnableWindow(hRightArrow, true);
			EnableWindow(hRightButton, true);
			SendMessage(hTrack, TBM_SETSEL, (WPARAM) true, (LPARAM) MAKELONG(process.trackleft, process.trackright));
			DragAcceptFiles(hWnd, true);
		}

		if (process.locate==LOCATE_RIP && !Stop_Flag)
		{
			MessageBeep(MB_OK);
			SetDlgItemText(hDlg, IDC_REMAIN, "FINISH");
		}
	}

	ExitThread(0);
}

LRESULT CALLBACK Statistics(HWND hStatisticsDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
		case WM_INITDIALOG:
			SendDlgItemMessage(hStatisticsDlg, IDC_PROGRESS, PBM_SETRANGE, 0, MAKELPARAM(0, 10000));
			return true;

		case WM_COMMAND:
			if (LOWORD(wParam) == IDCANCEL)
			{
				DestroyWindow(hStatisticsDlg);
				Statistics_Flag = false;
				return true;
			}
	}
    return false;
}

LRESULT CALLBACK Delay(HWND hDelayDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
		case WM_INITDIALOG:
			SetDlgItemText(hDelayDlg, IDC_DELAY, "0");
			return true;

		case WM_COMMAND:
			if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) 
			{
				SoundDelay[File_Limit] = GetDlgItemInt(hDelayDlg, IDC_DELAY, NULL, true);
				if (abs(SoundDelay[File_Limit]) > 10000000)
					SoundDelay[File_Limit] = 0;

				EndDialog(hDelayDlg, 0);
				return true;
			}
	}
    return false;
}

LRESULT CALLBACK About(HWND hAboutDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
		case WM_INITDIALOG:
			return true;

		case WM_COMMAND:
			if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) 
			{
				EndDialog(hAboutDlg, 0);
				return true;
			}
	}
    return false;
}

LRESULT CALLBACK Luminance(HWND hDialog, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
		case WM_INITDIALOG:
			LumDlg_Flag = true;

			SendDlgItemMessage(hDialog, IDC_GAIN_SLIDER, TBM_SETRANGE, 0, MAKELPARAM(0, 256));
			SendDlgItemMessage(hDialog, IDC_GAIN_SLIDER, TBM_SETTICFREQ, 128, 0);
			SendDlgItemMessage(hDialog, IDC_GAIN_SLIDER, TBM_SETPOS, 1, LumGain);
			sprintf(szTemp, "%d", LumGain-128);
			SetDlgItemText(hDialog, IDC_GAIN, szTemp);

			SendDlgItemMessage(hDialog, IDC_OFFSET_SLIDER, TBM_SETRANGE, 0, MAKELPARAM(0, 512));
			SendDlgItemMessage(hDialog, IDC_OFFSET_SLIDER, TBM_SETTICFREQ, 256, 0);
			SendDlgItemMessage(hDialog, IDC_OFFSET_SLIDER, TBM_SETPOS, 1, LumOffset+256);
			sprintf(szTemp, "%d", LumOffset);
			SetDlgItemText(hDialog, IDC_OFFSET, szTemp);

			ShowWindow(hDialog, SW_SHOW);

			if (Luminance_Flag)
				SendDlgItemMessage(hDialog, IDC_LUM_CHECK, BM_SETCHECK, BST_CHECKED, 0);
			return true;

		case WM_COMMAND:
			switch (LOWORD(wParam))
			{
				case IDC_LUM_CHECK:
					if (SendDlgItemMessage(hDialog, IDC_LUM_CHECK, BM_GETCHECK, 1, 0)==BST_CHECKED)
					{
						CheckMenuItem(hMenu, IDM_LUMINANCE, MF_CHECKED);
						Luminance_Flag = true;
					}
					else
					{
						CheckMenuItem(hMenu, IDM_LUMINANCE, MF_UNCHECKED);
						Luminance_Flag = false;
					}
					
					if (Check_Flag && WaitForSingleObject(hThread, 0)==WAIT_OBJECT_0)
					{
						Fault_Flag = false; Display_Flag = true;
						Write_Frame(backward_reference_frame, d2v_backward, 0);
					}
					break;

				case IDCANCEL:
					DestroyWindow(hDialog);
					LumDlg_Flag = false;
					return true;
			}
			break;

		case WM_HSCROLL:
			switch (GetWindowLong((HWND)lParam, GWL_ID))
			{
				case IDC_GAIN_SLIDER:
					LumGain = SendDlgItemMessage(hDialog, IDC_GAIN_SLIDER, TBM_GETPOS, 0, 0);
					LumGainMask = ((__int64)LumGain<<48) + ((__int64)LumGain<<32) + ((__int64)LumGain<<16) + (__int64)LumGain;
					sprintf(szTemp, "%d", LumGain-128);
					SetDlgItemText(hDialog, IDC_GAIN, szTemp);	
					break;

				case IDC_OFFSET_SLIDER:
					LumOffset = SendDlgItemMessage(hDialog, IDC_OFFSET_SLIDER, TBM_GETPOS, 0, 0) - 256;
					LumOffsetMask = ((__int64)LumOffset<<48) + ((__int64)LumOffset<<32) + ((__int64)LumOffset<<16) + (__int64)LumOffset;
					sprintf(szTemp, "%d", LumOffset);
					SetDlgItemText(hDialog, IDC_OFFSET, szTemp);
					break;
			}

			if (Check_Flag && WaitForSingleObject(hThread, 0)==WAIT_OBJECT_0)
			{
				Fault_Flag = false; Display_Flag = true;
				Write_Frame(backward_reference_frame, d2v_backward, 0);
			}
			break;
	}
    return false;
}

LRESULT CALLBACK Normalization(HWND hDialog, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
		case WM_INITDIALOG:
			NormDlg_Flag = true;

			SendDlgItemMessage(hDialog, IDC_NORM_SLIDER, TBM_SETRANGE, 0, MAKELPARAM(0, 100));
			SendDlgItemMessage(hDialog, IDC_NORM_SLIDER, TBM_SETTICFREQ, 50, 0);
			SendDlgItemMessage(hDialog, IDC_NORM_SLIDER, TBM_SETPOS, 1, Norm_Ratio);
			sprintf(szTemp, "%d", Norm_Ratio);
			SetDlgItemText(hDialog, IDC_NORM, szTemp);

			ShowWindow(hDialog, SW_SHOW);

			if (Normalization_Flag)
				SendDlgItemMessage(hDialog, IDC_NORM_CHECK, BM_SETCHECK, BST_CHECKED, 0);
			return true;

		case WM_COMMAND:
			switch (LOWORD(wParam))
			{
				case IDC_NORM_CHECK:
					if (SendDlgItemMessage(hDialog, IDC_NORM_CHECK, BM_GETCHECK, 1, 0)==BST_CHECKED)
					{
						CheckMenuItem(hMenu, IDM_NORM, MF_CHECKED);
						Normalization_Flag = true;
					}
					else
					{
						CheckMenuItem(hMenu, IDM_NORM, MF_UNCHECKED);
						Normalization_Flag = false;
					}
					break;

				case IDCANCEL:
					DestroyWindow(hDialog);
					NormDlg_Flag = false;
					return true;
			}
			break;

		case WM_HSCROLL:
			if (GetWindowLong((HWND)lParam, GWL_ID)==IDC_NORM_SLIDER)
			{
				Norm_Ratio = SendDlgItemMessage(hDialog, IDC_NORM_SLIDER, TBM_GETPOS, 0, 0);
				sprintf(szTemp, "%d", Norm_Ratio);
				SetDlgItemText(hDialog, IDC_NORM, szTemp);
			}
			break;
	}
    return false;
}

/* register the window class */
ATOM MyRegisterClass(HINSTANCE hInstance)
{
	WNDCLASSEX wcex;

	wcex.cbSize			= sizeof(WNDCLASSEX);
	wcex.style			= CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc	= (WNDPROC)WndProc;
	wcex.cbClsExtra		= false;
	wcex.cbWndExtra		= false;
	wcex.hInstance		= hInstance;
	wcex.hIcon			= LoadIcon(hInstance, (LPCTSTR)IDI_MOVIE);
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground	= CreateSolidBrush(MASKCOLOR);
	wcex.lpszMenuName	= (LPCSTR)IDC_GUI;
	wcex.lpszClassName	= szWindowClass;
	wcex.hIconSm		= LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);

	return RegisterClassEx(&wcex);
}

char *ExtFilter[3] = 
{
	".avi", ".d2v", ".wav"
};

BOOL PopFileDlg(PTSTR pstrFileName, HWND hOwner, int Status)
{
	static char *szFilter, *ext;	
	int count = 0;

	switch (Status)
	{
		case OPEN_VOB:
			szFilter = TEXT ("MPEG-2 Stream (*.vob; *.m2p; *.m2v)\0*.vob;*.m2p;*.m2v\0")  \
				TEXT ("All Files (*.*)\0*.*\0");
			break;

		case SAVE_AVI:
			szFilter = TEXT ("AVI File (*.avi)\0*.avi; *.ac3; *.wav; *.mpa\0")  \
				TEXT ("All Files (*.*)\0*.*\0");
			break;

		case OPEN_D2V:
			szFilter = TEXT ("DVD2AVI Project File (*.d2v)\0*.d2v\0")  \
				TEXT ("All Files (*.*)\0*.*\0");
			break;

		case SAVE_D2V:
			szFilter = TEXT ("DVD2AVI Project File (*.d2v)\0*.d2v; *.ac3; *.wav; *.mpa\0")  \
				TEXT ("All Files (*.*)\0*.*\0");
			break;

		case OPEN_WAV:
		case SAVE_WAV:
			szFilter = TEXT ("WAV File (*.wav)\0*.wav\0")  \
				TEXT ("All Files (*.*)\0*.*\0");
			break;
	}

	ofn.lStructSize       = sizeof (OPENFILENAME) ;
	ofn.hwndOwner         = hOwner ;
	ofn.hInstance         = hInst ;
	ofn.lpstrFilter       = szFilter ;
	ofn.nMaxFile          = _MAX_PATH ;
	ofn.nMaxFileTitle     = _MAX_PATH ;
	ofn.lpstrFile         = pstrFileName ;

	switch (Status)
	{
		case OPEN_VOB:
		case OPEN_D2V:
		case OPEN_WAV:
			ofn.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST;
			return GetOpenFileName(&ofn);

		case SAVE_WAV:
			count++;
		case SAVE_D2V:
			count++;
		case SAVE_AVI:
			ofn.Flags = OFN_HIDEREADONLY | OFN_ALLOWMULTISELECT | OFN_EXPLORER;
			if (GetSaveFileName(&ofn))
			{
				ext = strrchr(pstrFileName, '.');

				if (ext!=NULL && !_strnicmp(ext, ExtFilter[count], 4))
					strncpy(ext, ext+4, 1);

				return true;
			}
	}

	return false;
}

static DWORD DDColorMatch(LPDIRECTDRAWSURFACE pdds, COLORREF rgb)
{
    COLORREF                rgbT;
    DWORD                   dw = CLR_INVALID;
    HRESULT                 hres;
	HDC						hdc;

    if (IDirectDrawSurface_GetDC(pdds, &hdc)==DD_OK)
    {
        rgbT = GetPixel(hdc, 0, 0);     // Save current pixel value
        SetPixel(hdc, 0, 0, rgb);       // Set our value
        IDirectDrawSurface_ReleaseDC(pdds, hdc);
    }

	ZeroMemory(&ddsd, sizeof(DDSURFACEDESC));
    ddsd.dwSize = sizeof(DDSURFACEDESC);
    while ((hres = IDirectDrawSurface_Lock(pdds, NULL, &ddsd, 0, NULL)) == DDERR_WASSTILLDRAWING)
        ;

    if (hres==DD_OK)
    {
        dw = *(DWORD *) ddsd.lpSurface;
        if (ddsd.ddpfPixelFormat.dwRGBBitCount < 32)
            dw &= (1 << ddsd.ddpfPixelFormat.dwRGBBitCount) - 1;
        IDirectDrawSurface_Unlock(pdds, NULL);
    }

    if (IDirectDrawSurface_GetDC(pdds, &hdc)==DD_OK)
    {
        SetPixel(hdc, 0, 0, rgbT);
        IDirectDrawSurface_ReleaseDC(pdds, hdc);
    }
    return dw;
}

static void ShowStatistics(int refresh)
{
	if (refresh)
	{
		if (Statistics_Flag)
			DestroyWindow(hDlg);

		Statistics_Flag = true;
		hDlg = CreateDialog(hInst, (LPCTSTR)IDD_STATISTICS, hWnd, (DLGPROC)Statistics);
	}

	if (Statistics_Flag)
	{
		// resize window
		GetWindowRect(hDlg, &crect);
		GetWindowRect(hWnd, &wrect);
		MoveWindow(hDlg, wrect.right, wrect.top+Edge_Height-Edge_Width/2, crect.right-crect.left, crect.bottom-crect.top, true);
		ShowWindow(hDlg, SW_SHOW);
		SetFocus(hWnd);
	}
}

static void DisableControl()
{
	EnableWindow(hTrack, false);
	EnableWindow(hLeftButton, false);
	EnableWindow(hLeftArrow, false);
	EnableWindow(hRightArrow, false);
	EnableWindow(hRightButton, false);

	DragAcceptFiles(hWnd, false);
}

static void ClearTrack()
{
	CheckMenuItem(hMenu, IDM_TRACK_NONE, MF_UNCHECKED);
	CheckMenuItem(hMenu, IDM_TRACK_1, MF_UNCHECKED);
	CheckMenuItem(hMenu, IDM_TRACK_2, MF_UNCHECKED);
	CheckMenuItem(hMenu, IDM_TRACK_3, MF_UNCHECKED);
	CheckMenuItem(hMenu, IDM_TRACK_4, MF_UNCHECKED);
	CheckMenuItem(hMenu, IDM_TRACK_5, MF_UNCHECKED);
	CheckMenuItem(hMenu, IDM_TRACK_6, MF_UNCHECKED);
	CheckMenuItem(hMenu, IDM_TRACK_7, MF_UNCHECKED);
	CheckMenuItem(hMenu, IDM_TRACK_8, MF_UNCHECKED);
}

static void CheckCPU()
{
	__asm
	{
		mov			eax, 1
		cpuid
		test		edx, 0x00800000
		jz			TEST_SSE
		mov			[cpu.mmx], 1
TEST_SSE:
		test		edx, 0x02000000
		jz			TEST_AMD
		mov			[cpu.sse], 1
TEST_AMD:
		mov			eax, 0x80000001
		cpuid
		test		edx, 0x80000000
		jz			TEST_END
		mov			[cpu.amd], 1
TEST_END:
	}

	if (cpu.mmx)
		CheckMenuItem(hMenu, IDM_MMX, MF_CHECKED);

	if (cpu.sse)
		CheckMenuItem(hMenu, IDM_SSE, MF_CHECKED);

	if (cpu.amd)
		CheckMenuItem(hMenu, IDM_AMD, MF_CHECKED);

	EnableMenuItem(hMenu, IDM_SSE, MF_GRAYED);
	EnableMenuItem(hMenu, IDM_AMD, MF_GRAYED);
}

static void CheckINI()
{
	if ((INIFile = fopen("DVD2AVI.ini", "r")) == NULL)
	{
NEW_VERSION:
		INIT_X = 0;
		INIT_Y = 0;
		INI_Version = INI_VERSION;
		iDCT_Flag = IDCT_MMX;
		Scale_Flag = true;
		FO_Flag = FO_NONE;
		Track_Flag = TRACK_1;
		Format_Flag = FORMAT_AUTO;
		AC3_Flag = AUDIO_DECODE;
		DRC_Flag = DRC_NORMAL;
		DSDown_Flag = false;
		MPA_Flag = AUDIO_DEMUXONE;
		SRC_Flag = SRC_NONE;
		Norm_Ratio = 100;
		Priority_Flag = PRIORITY_NORMAL;
	}
	else
	{
		fscanf(INIFile, "INI_Version=%d\n", &INI_Version);
		if (INI_Version != INI_VERSION)
		{
			fclose(INIFile);
			goto NEW_VERSION;
		}

		fscanf(INIFile, "INIT_X=%d\n", &INIT_X);
		fscanf(INIFile, "INIT_Y=%d\n", &INIT_Y);
		fscanf(INIFile, "iDCT_Algorithm=%d\n", &iDCT_Flag);
		fscanf(INIFile, "YUVRGB_Scale=%d\n", &Scale_Flag);
		fscanf(INIFile, "Field_Operation=%d\n", &FO_Flag);
		fscanf(INIFile, "Track_Number=%d\n", &Track_Flag);
		fscanf(INIFile, "Channel_Format=%d\n", &Format_Flag);
		fscanf(INIFile, "AC3=%d\n", &AC3_Flag);
		fscanf(INIFile, "DR_Control=%d\n", &DRC_Flag);
		fscanf(INIFile, "DS_Downmix=%d\n", &DSDown_Flag);
		fscanf(INIFile, "MPA=%d\n", &MPA_Flag);
		fscanf(INIFile, "SRC_Precision=%d\n", &SRC_Flag);
		fscanf(INIFile, "Norm_Ratio=%d\n", &Norm_Ratio);
		fscanf(INIFile, "Process_Priority=%d\n", &Priority_Flag);

		fclose(INIFile);
	}
}

static void CheckFlag()
{
	CheckMenuItem(hMenu, IDM_IDCT_MMX, MF_UNCHECKED);
	CheckMenuItem(hMenu, IDM_IDCT_FPU, MF_UNCHECKED);
	CheckMenuItem(hMenu, IDM_IDCT_REF, MF_UNCHECKED);
	CheckMenuItem(hMenu, IDM_PCSCALE, MF_UNCHECKED);
	CheckMenuItem(hMenu, IDM_TVSCALE, MF_UNCHECKED);
	CheckMenuItem(hMenu, IDM_FO_FILM, MF_UNCHECKED);

	switch (iDCT_Flag)
	{
		case IDCT_MMX:
			CheckMenuItem(hMenu, IDM_IDCT_MMX, MF_CHECKED);
			break;

		case IDCT_FPU:
			CheckMenuItem(hMenu, IDM_IDCT_FPU, MF_CHECKED);
			break;

		case IDCT_REF:
			CheckMenuItem(hMenu, IDM_IDCT_REF, MF_CHECKED);
			break;
	}

	if (Scale_Flag)
	{
		YUVRGB_Scale = 0x1000254310002543;
		YUVRGB_Offset = 0x0010001000100010;
		CheckMenuItem(hMenu, IDM_PCSCALE, MF_CHECKED);
	}
	else
	{
		YUVRGB_Scale = 0x1000200010002000;
		YUVRGB_Offset = 0x0000000000000000;
		CheckMenuItem(hMenu, IDM_TVSCALE, MF_CHECKED);
	}

	switch (FO_Flag)
	{
		case FO_NONE:
			CheckMenuItem(hMenu, IDM_FO_NONE, MF_CHECKED);
			CheckMenuItem(hMenu, IDM_FO_FILM, MF_UNCHECKED);
			CheckMenuItem(hMenu, IDM_FO_SWAP, MF_UNCHECKED);
			break;

		case FO_FILM:
			CheckMenuItem(hMenu, IDM_FO_NONE, MF_UNCHECKED);
			CheckMenuItem(hMenu, IDM_FO_FILM, MF_CHECKED);
			CheckMenuItem(hMenu, IDM_FO_SWAP, MF_UNCHECKED);
			break;

		case FO_SWAP:
			CheckMenuItem(hMenu, IDM_FO_NONE, MF_UNCHECKED);
			CheckMenuItem(hMenu, IDM_FO_FILM, MF_UNCHECKED);
			CheckMenuItem(hMenu, IDM_FO_SWAP, MF_CHECKED);
			break;
	}

	switch (Track_Flag)
	{
		case TRACK_NONE:
			CheckMenuItem(hMenu, IDM_TRACK_NONE, MF_CHECKED);
			break;

		case TRACK_1:
			CheckMenuItem(hMenu, IDM_TRACK_1, MF_CHECKED);
			break;

		case TRACK_2:
			CheckMenuItem(hMenu, IDM_TRACK_2, MF_CHECKED);
			break;

		case TRACK_3:
			CheckMenuItem(hMenu, IDM_TRACK_3, MF_CHECKED);
			break;

		case TRACK_4:
			CheckMenuItem(hMenu, IDM_TRACK_4, MF_CHECKED);
			break;

		case TRACK_5:
			CheckMenuItem(hMenu, IDM_TRACK_5, MF_CHECKED);
			break;

		case TRACK_6:
			CheckMenuItem(hMenu, IDM_TRACK_6, MF_CHECKED);
			break;

		case TRACK_7:
			CheckMenuItem(hMenu, IDM_TRACK_7, MF_CHECKED);
			break;

		case TRACK_8:
			CheckMenuItem(hMenu, IDM_TRACK_8, MF_CHECKED);
			break;
	}

	switch (Format_Flag)
	{
		case FORMAT_AC3:
			CheckMenuItem(hMenu, IDM_AC3, MF_CHECKED);
			break;

		case FORMAT_MPA:
			CheckMenuItem(hMenu, IDM_MPA, MF_CHECKED);
			break;

		case FORMAT_LPCM:
			CheckMenuItem(hMenu, IDM_LPCM, MF_CHECKED);
			break;

		case FORMAT_AUTO:
			CheckMenuItem(hMenu, IDM_SELECT, MF_CHECKED);
			break;
	}

	switch (AC3_Flag)
	{
		case AUDIO_DEMUXALL:
			CheckMenuItem(hMenu, IDM_AC3_DEMUXALL, MF_CHECKED);
			break;

		case AUDIO_DEMUXONE:
			CheckMenuItem(hMenu, IDM_AC3_DEMUXONE, MF_CHECKED);
			break;

		case AUDIO_DECODE:
			CheckMenuItem(hMenu, IDM_AC3_DECODE, MF_CHECKED);
			break;
	}

	switch (DRC_Flag)
	{
		case DRC_NONE:
			CheckMenuItem(hMenu, IDM_DRC_NONE, MF_CHECKED);
			break;

		case DRC_LIGHT:
			CheckMenuItem(hMenu, IDM_DRC_LIGHT, MF_CHECKED);
			break;

		case DRC_NORMAL:
			CheckMenuItem(hMenu, IDM_DRC_NORMAL, MF_CHECKED);
			break;

		case DRC_HEAVY:
			CheckMenuItem(hMenu, IDM_DRC_HEAVY, MF_CHECKED);
			break;
	}

	if (DSDown_Flag)
		CheckMenuItem(hMenu, IDM_DSDOWN, MF_CHECKED);

	switch (MPA_Flag)
	{
		case AUDIO_DEMUXALL:
			CheckMenuItem(hMenu, IDM_MPA_DEMUXALL, MF_CHECKED);
			break;

		case AUDIO_DEMUXONE:
			CheckMenuItem(hMenu, IDM_MPA_DEMUXONE, MF_CHECKED);
			break;
	}

	switch (SRC_Flag)
	{
		case SRC_NONE:
			CheckMenuItem(hMenu, IDM_SRC_NONE, MF_CHECKED);
			break;

		case SRC_LOW:
			CheckMenuItem(hMenu, IDM_SRC_LOW, MF_CHECKED);
			break;

		case SRC_MID:
			CheckMenuItem(hMenu, IDM_SRC_MID, MF_CHECKED);
			break;

		case SRC_HIGH:
			CheckMenuItem(hMenu, IDM_SRC_HIGH, MF_CHECKED);
			break;

		case SRC_UHIGH:
			CheckMenuItem(hMenu, IDM_SRC_UHIGH, MF_CHECKED);
			break;
	}

	if (Norm_Ratio > 100)
	{
		CheckMenuItem(hMenu, IDM_NORM, MF_CHECKED);
		Normalization_Flag = true;
		Norm_Ratio -= 100;
	}

	switch (Priority_Flag)
	{
		case PRIORITY_HIGH:
			CheckMenuItem(hMenu, IDM_PP_HIGH, MF_CHECKED);
			SetPriorityClass(hProcess, HIGH_PRIORITY_CLASS);
			break;

		case PRIORITY_NORMAL:
			CheckMenuItem(hMenu, IDM_PP_NORMAL, MF_CHECKED);
			break;

		case PRIORITY_LOW:
			CheckMenuItem(hMenu, IDM_PP_LOW, MF_CHECKED);
			SetPriorityClass(hProcess, IDLE_PRIORITY_CLASS);
			break;
	}
}

static void Recovery()
{
	int i;

	if (Check_Flag)
	{
		if (lpDD2)
			lpDD2->Release();
		if (lpDD)
			lpDD->Release();

		for (i=0; i<3; i++)
		{
			free(backward_reference_frame[i]);
			free(forward_reference_frame[i]);
			free(auxframe[i]);
		}

		free(u422);
		free(v422);
		free(u444);
		free(v444);
		free(rgb24);
		free(yuy2);
		free(lum);
	}

	Check_Flag = false;
	DDOverlay_Flag = false;

	EnableMenuItem(hMenu, 1, MF_BYPOSITION | MF_GRAYED);
	CheckMenuItem(hMenu, IDM_DIRECTDRAW, MF_UNCHECKED);

	SendMessage(hTrack, TBM_SETPOS, (WPARAM) true, 0);
	SendMessage(hTrack, TBM_SETSEL, (WPARAM) true, (LPARAM) MAKELONG(0, 0));

	DisableControl();

	EnableMenuItem(hMenu, IDM_PREVIEW, MF_GRAYED);
	EnableMenuItem(hMenu, IDM_SAVE, MF_GRAYED);
	EnableMenuItem(hMenu, IDM_SAVE_D2V, MF_GRAYED);
	EnableMenuItem(hMenu, IDM_BMP, MF_GRAYED);
	EnableMenuItem(hMenu, IDM_PROCESS_WAV, MF_ENABLED);

	SetWindowText(hWnd, "DVD2AVI");

	if (File_Limit)
	{
		EnableMenuItem(hMenu, IDM_PROCESS_WAV, MF_GRAYED);

		ZeroMemory(&process, sizeof(PROCESS));
		process.trackright = TRACK_PITCH;

		SystemStream_Flag = false;
		Display_Flag = true;

		for (i=0; i<File_Limit; i++)
		{
			process.length[i] = _filelengthi64(Infile[i]);
			process.total += process.length[i];
		}
	}
	else
		DragAcceptFiles(hWnd, true);
}

void ResizeWindow(int width, int height)
{
	GetWindowRect(hWnd, &wrect);
	MoveWindow(hTrack, 0, height, width-4*TRACK_HEIGHT, TRACK_HEIGHT, true);
	MoveWindow(hLeftButton, width-4*TRACK_HEIGHT, height, TRACK_HEIGHT, TRACK_HEIGHT, true);
	MoveWindow(hLeftArrow, width-3*TRACK_HEIGHT, height, TRACK_HEIGHT, TRACK_HEIGHT, true);
	MoveWindow(hRightArrow, width-2*TRACK_HEIGHT, height, TRACK_HEIGHT, TRACK_HEIGHT, true);
	MoveWindow(hRightButton, width-TRACK_HEIGHT, height, TRACK_HEIGHT, TRACK_HEIGHT, true);
	MoveWindow(hWnd, wrect.left, wrect.top, width+Edge_Width, height+Edge_Height+TRACK_HEIGHT, true);
}

void CheckDirectDraw(int width, int height)
{
	if (DirectDrawCreate(NULL, &lpDD, NULL)==DD_OK)
	{
		if (lpDD->QueryInterface(IID_IDirectDraw2, (LPVOID*)&lpDD2)==DD_OK)
		{
			if (lpDD2->SetCooperativeLevel(hWnd, DDSCL_NORMAL)==DD_OK)
			{
				ZeroMemory(&ddsd, sizeof(DDSURFACEDESC));
				ddsd.dwSize = sizeof(DDSURFACEDESC);
				ddsd.dwFlags = DDSD_CAPS;
				ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_VIDEOMEMORY;

				if (lpDD2->CreateSurface(&ddsd, &lpPrimary, NULL)==DD_OK)
				{
					ZeroMemory(&halcaps, sizeof(DDCAPS));
					halcaps.dwSize = sizeof(DDCAPS);

					if (lpDD2->GetCaps(&halcaps, NULL)==DD_OK)
					{
						if (halcaps.dwCaps & DDCAPS_OVERLAY)
						{
							DDPIXELFORMAT ddPixelFormat;
							ddPixelFormat.dwFlags = DDPF_FOURCC;
							ddPixelFormat.dwFourCC = mmioFOURCC('Y','U','Y','2');
							ddPixelFormat.dwYUVBitCount = 16;

							ZeroMemory(&ddsd, sizeof(DDSURFACEDESC));
							ddsd.dwSize = sizeof(DDSURFACEDESC);
							ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
							ddsd.ddsCaps.dwCaps = DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY;
							ddsd.dwWidth = width;
							ddsd.dwHeight = height;

							memcpy(&(ddsd.ddpfPixelFormat), &ddPixelFormat, sizeof(DDPIXELFORMAT));

							if (lpDD2->CreateSurface(&ddsd, &lpOverlay, NULL)==DD_OK)
							{
								DDOverlay_Flag = true;
								CheckMenuItem(hMenu, IDM_DIRECTDRAW, MF_CHECKED);

								ZeroMemory(&ddofx, sizeof(DDOVERLAYFX));
								ddofx.dwSize = sizeof(DDOVERLAYFX);

								ddofx.dckDestColorkey.dwColorSpaceLowValue = DDColorMatch(lpPrimary, MASKCOLOR);
								ddofx.dckDestColorkey.dwColorSpaceHighValue = ddofx.dckDestColorkey.dwColorSpaceLowValue;
							}
						}
					}
				}
			}
		}
	}

	if (DDOverlay_Flag)
	{
		Store_Flag = STORE_YUY2;
		CheckMenuItem(hMenu, IDM_STORE_RGB24, MF_UNCHECKED);
		CheckMenuItem(hMenu, IDM_STORE_YUY2, MF_CHECKED);
		EnableMenuItem(hMenu, IDM_BMP, MF_GRAYED);
	}
	else
	{
		Store_Flag = STORE_RGB24;
		CheckMenuItem(hMenu, IDM_STORE_RGB24, MF_CHECKED);
		CheckMenuItem(hMenu, IDM_STORE_YUY2, MF_UNCHECKED);
		EnableMenuItem(hMenu, IDM_BMP, MF_ENABLED);
	}
}